#include "bsp_adc.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "Mini58Series.h"

#include "lite-log.h"

static BSP_ADC_ST bsp_adc;

volatile uint16_t adc_sample_times_tab[ADC_CHANNEL_NUM] = {200, 100};

#define POOL_PARA 10

void bsp_ADC_init(void) {
  memset((uint8_t *)&bsp_adc, 0, sizeof(BSP_ADC_ST));
  //  bsp_adc.result = 500;
  //  bsp_adc.result_sum = bsp_adc.result * POOL_PARA;

  /* Unlock protected registers */
  SYS_UnlockReg();

  SYS_ResetModule(ADC_RST);

  CLK_EnableModuleClock(ADC_MODULE);
  CLK_SetModuleClock(ADC_MODULE, CLK_CLKSEL1_ADCSEL_HIRC, CLK_CLKDIV_ADC(8));

  SYS->P3_MFP |= SYS_MFP_P30_ADC_CH6;
  SYS->P5_MFP |= SYS_MFP_P53_ADC_CH0;

  /* Analog pin OFFD to prevent leakage */
  P3->DINOFF |= (0x00000001 << GP_DINOFF_DINOFF0_Pos);
  P5->DINOFF |= (0x00000001 << GP_DINOFF_DINOFF3_Pos);

  /* Lock protected registers */
  SYS_LockReg();
  ///

  //	GPIO_SetMode(P3, BIT0, GPIO_MODE_INPUT);

  // Enable channel 6
  // ADC_Open(ADC, 0, 0, BIT6);
  // ADC_Open(ADC, 0, 0, BIT0);

  // Power on ADC
  ADC_POWER_ON(ADC);

  // Enable ADC convert complete interrupt
  ADC_EnableInt(ADC, ADC_ADIF_INT);
  NVIC_EnableIRQ(ADC_IRQn);
}

BSP_ADC_ST *bsp_ADC_ST_get(void) { return &bsp_adc; }

void bsp_ADC_start(void) {
  uint8_t i = 0;
  if (bsp_adc.busy) {
    return;
  }
  bsp_adc.busy = 1;
  bsp_adc.finish = 0;
  bsp_adc.adc_ch = 0;
  for (i = 0; i < ADC_CHANNEL_NUM; i++) {
    bsp_adc.channel[i].max = 0;
    bsp_adc.channel[i].min = ADC_MAX_VALUE - 5;
    bsp_adc.channel[i].result_sum = 0;
    bsp_adc.channel[i].average = 0;
    bsp_adc.channel[i].cnt = adc_sample_times_tab[i];
    bsp_adc.channel[i].finish = 0;
  }
  ADC->CHEN &= ~0xFF;
  ADC->CHEN |= ADC_CHEN_CHEN0_Msk;
  ADC_START_CONV(ADC);
}

static uint32_t u32Flag;
// average = 0;
// static uint8_t tmp_low_power = 0;
void ADC_IRQHandler(void) {
  // Get ADC comparator interrupt flag
  u32Flag = ADC_GET_INT_FLAG(ADC, ADC_ADIF_INT);
  // u32Flag = ADC->STATUS & ADC_ADIF_INT;

#if 0
  adc_st.result_sum += ADC_GET_CONVERSION_DATA(ADC, 0);
  average = adc_st.result_sum / POOL_PARA;
  adc_st.result_sum -= average;
  adc_st.result = average & 0xFFFF;
#else

#if 0
  bsp_adc.result = ADC_GET_CONVERSION_DATA(ADC, 0);
  if (bsp_adc.result < 449) {
    tmp_low_power |= 0x01;
    if ((tmp_low_power & 0x07) == 0x07) {
      // LOW_POWER_OUT_IO = 0;
      //  AMP_8835_RST_IO = 0;
      // bsp_relay_power_boost_write(0);
      low_power_st.alert_flag = 1;
    }
  }
  tmp_low_power <<= 1;
#endif
  if (bsp_adc.channel[bsp_adc.adc_ch].cnt) {
    bsp_adc.channel[bsp_adc.adc_ch].cnt--;
    bsp_adc.adc_tmp_buf[bsp_adc.adc_ch] = ADC_GET_CONVERSION_DATA(ADC, 0);
    bsp_adc.channel[bsp_adc.adc_ch].result_sum +=
        bsp_adc.adc_tmp_buf[bsp_adc.adc_ch];
    if (bsp_adc.adc_tmp_buf[bsp_adc.adc_ch] >
        bsp_adc.channel[bsp_adc.adc_ch].max) {
      bsp_adc.channel[bsp_adc.adc_ch].max = bsp_adc.adc_tmp_buf[bsp_adc.adc_ch];
    }
    if (bsp_adc.adc_tmp_buf[bsp_adc.adc_ch] <
        bsp_adc.channel[bsp_adc.adc_ch].min) {
      bsp_adc.channel[bsp_adc.adc_ch].min = bsp_adc.adc_tmp_buf[bsp_adc.adc_ch];
    }
  }
  if (bsp_adc.channel[bsp_adc.adc_ch].cnt) {
    ADC_START_CONV(ADC);
  } else {
    bsp_adc.channel[bsp_adc.adc_ch].result_sum -=
        bsp_adc.channel[bsp_adc.adc_ch].max;
    bsp_adc.channel[bsp_adc.adc_ch].result_sum -=
        bsp_adc.channel[bsp_adc.adc_ch].min;
    bsp_adc.channel[bsp_adc.adc_ch].average =
        bsp_adc.channel[bsp_adc.adc_ch].result_sum /
        (adc_sample_times_tab[bsp_adc.adc_ch] - 2);
    bsp_adc.channel[bsp_adc.adc_ch].result_sum = 0;
    bsp_adc.channel[bsp_adc.adc_ch].finish = 1;
    bsp_adc.adc_ch++;
    if (bsp_adc.adc_ch >= ADC_CHANNEL_NUM) {
      ADC_STOP_CONV(ADC);
      bsp_adc.adc_ch = 0;
      bsp_adc.finish = 1;
      bsp_adc.busy = 0;
    } else {
      // Adc_CfgSglChannel(AdcExInputCH0 + bsp_adc.adc_ch);
      // Adc_SGL_Start();
      ADC->CHEN &= ~0xFF;
      if (bsp_adc.adc_ch == 0) {
        ADC->CHEN |= ADC_CHEN_CHEN0_Msk;
        ADC_START_CONV(ADC);
      } else if (bsp_adc.adc_ch == 1) {
        ADC->CHEN |= ADC_CHEN_CHEN6_Msk;
        ADC_START_CONV(ADC);
      } else {
        ADC_STOP_CONV(ADC);
        bsp_adc.busy = 0;
      }
 //     log_debug("adc switch %u", bsp_adc.adc_ch);
    }
  }

#endif
  ADC_CLR_INT_FLAG(ADC, u32Flag);
}
